package cn.xenosp.server.module.scheduler.service;

import cn.hutool.core.date.DateUtil;
import cn.xenosp.server.common.scheduler.BaseSchedulerTask;
import cn.xenosp.server.common.tools.SpringBeanUtil;
import cn.xenosp.server.module.scheduler.entity.ScheduledTask;
import cn.xenosp.server.module.scheduler.entity.ScheduledTaskLog;
import cn.xenosp.server.module.scheduler.logs.ConsoleLogCapture;
import cn.xenosp.server.module.scheduler.logs.TaskLogService;
import cn.xenosp.server.module.scheduler.mapper.ScheduledTaskMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.TaskScheduler;
import org.springframework.scheduling.Trigger;
import org.springframework.scheduling.TriggerContext;
import org.springframework.scheduling.annotation.SchedulingConfigurer;
import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;
import org.springframework.scheduling.config.ScheduledTaskRegistrar;
import org.springframework.scheduling.support.CronTrigger;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledFuture;

/**
 * 项目名： service-web
 * 包路径： cn.xenosp.server.module.scheduler
 * 作者：   TongHui
 * 创建时间: 2025-11-20 15:05
 * 描述: TODO
 * 版本: 1.0
 */
@Slf4j
@Service
public class DynamicTaskScheduler implements SchedulingConfigurer {
    @Autowired
    private ScheduledTaskMapper scheduledTaskMapper;
    @Autowired
    private TaskLogService taskLogService;

    @Autowired
    private ConsoleLogCapture consoleLogCapture;


    private ScheduledTaskRegistrar taskRegistrar;
    private final Map<String, ScheduledFuture<?>> taskFutures = new ConcurrentHashMap<>();
    private final Map<String, String> currentExecutions = new ConcurrentHashMap<>();
    private final Map<String, ScheduledTask> lastTaskConfigs = new ConcurrentHashMap<>();
    @Override
    public void configureTasks(ScheduledTaskRegistrar taskRegistrar) {
        log.info("============================初始化定时任务===============================");
        this.taskRegistrar = taskRegistrar;
        // 如果getScheduler()返回null，则手动设置一个调度器
        if (taskRegistrar.getScheduler() == null) {
            // 创建一个线程池大小为5的线程池任务调度器
            ThreadPoolTaskScheduler scheduler = new ThreadPoolTaskScheduler();
            scheduler.setPoolSize(2);
            scheduler.setThreadNamePrefix("定时任务-");
            scheduler.initialize();
            taskRegistrar.setScheduler(scheduler);
        }
        // 启动时加载所有启用的任务
        loadEnabledTasks();
        log.info("============================完成初始化定时任务===============================");
    }

    private void loadEnabledTasks() {
        List<ScheduledTask> tasks = scheduledTaskMapper.list();
        for (ScheduledTask task : tasks) {
            if (task.isStart()) {
                lastTaskConfigs.put(task.getId(), task);
                scheduleTask(task);
            }
        }
    }

    public boolean addTask(ScheduledTask task) {
        if (task.isStart()) {
            lastTaskConfigs.put(task.getId(), task);
            scheduleTask(task);
            return true;
        }
        return false;
    }

    public boolean updateTask(ScheduledTask task) {
        // 先停止现有任务
        stopScheduling(task.getId());
        // 如果启用则重新调度
        if (task.isStart()) {
            scheduleTask(task);
        }
        lastTaskConfigs.put(task.getId(), task);
        return true;
    }

    public boolean deleteTask(String taskId) {
        lastTaskConfigs.remove(taskId);
        ScheduledTask task = scheduledTaskMapper.selectById(taskId);
        stopTask(task);
        return true;
    }

    public boolean startTask(String taskId) {
        ScheduledTask task = scheduledTaskMapper.selectById(taskId);
        if (task != null) {
//            task.setEnabled(1);
            task.setStatus("RUNNING");
            scheduledTaskMapper.updateById(task);
            scheduleTask(task);
            return true;
        }
        return false;
    }

    public boolean stopTask(ScheduledTask task) {
        if (task != null) {
//            task.setEnabled(0);
            task.setStatus("STOPPED");
            scheduledTaskMapper.updateById(task);

            ScheduledFuture<?> future = taskFutures.get(task.getId());
            if (future != null) {
                future.cancel(true);
                taskFutures.remove(task.getId());
            }
            return true;
        }
        return false;
    }
    /**
     * 停止任务的调度（但不中断正在执行的任务）
     */
    private void stopScheduling(String taskId) {
        ScheduledFuture<?> future = taskFutures.get(taskId);
        if (future != null) {
            // 只取消调度，不中断正在执行的任务
            future.cancel(false);
            taskFutures.remove(taskId);
        }
        lastTaskConfigs.remove(taskId);
    }
    /**
     * 调度任务执行
     */
    private void scheduleTask(ScheduledTask task) {
        if (taskRegistrar == null) {
            return;
        }
        // 检查是否已经有该任务的调度
        if (taskFutures.containsKey(task.getId())) {
            stopScheduling(task.getId());
        }
        Runnable runnable = createRunnable(task);
        Trigger trigger = createTrigger(task);
        TaskScheduler scheduler = taskRegistrar.getScheduler();
        ScheduledFuture<?> future = scheduler.schedule(runnable, trigger);
        taskFutures.put(task.getId(), future);
//        task.setStatus("RUNNING");
//        scheduledTaskMapper.updateById(task);
    }

    private Runnable createRunnable(ScheduledTask task) {
        return () -> {
            ScheduledTaskLog scheduledTaskLog = null;
            String logId = null;
            try {
                // 创建执行日志
                scheduledTaskLog = new ScheduledTaskLog(task.getId(), task.getName());
                logId = taskLogService.addLog(scheduledTaskLog);
                currentExecutions.put(task.getId(), logId);
                // 开始捕获控制台日志
                consoleLogCapture.startCapture(logId);
                // 更新最后执行时间
                task.setLastExecuteTime(DateUtil.date());
                scheduledTaskMapper.updateById(task);
                task.setStatus("RUNNING");
                scheduledTaskMapper.updateById(task);

                // 执行任务
                executeTask(task,logId);
                // 停止捕获并保存控制台日志
                String consoleLog = consoleLogCapture.stopCapture(logId);
                scheduledTaskLog.setConsoleLog(consoleLog);
                // 记录成功日志
                scheduledTaskLog.markSuccess("执行成功");
                taskLogService.updateById(scheduledTaskLog);
                task.setStatus("STOPPED");
                scheduledTaskMapper.updateById(task);

            } catch (Exception e) {
                // 停止捕获并保存控制台日志
                if (logId != null) {
                    String consoleLog = consoleLogCapture.stopCapture(logId);
                    scheduledTaskLog.setConsoleLog(consoleLog);
                    // 记录失败日志
                    scheduledTaskLog.markFailed(e.getMessage());
                    taskLogService.updateById(scheduledTaskLog);
                }
                task.setStatus("ERROR");
                scheduledTaskMapper.updateById(task);
                e.printStackTrace();
            }finally {
                currentExecutions.remove(task.getId());
            }
        };
    }

    private Trigger createTrigger(ScheduledTask task) {
        return (TriggerContext triggerContext) -> {
            CronTrigger cronTrigger = new CronTrigger(task.getCronExpression());
            return cronTrigger.nextExecutionTime(triggerContext);
        };
    }

    private void executeTask(ScheduledTask task,String logid) {
        try {
            consoleLogCapture.writeToBuffer(logid,this.getClass().getPackage().getName() +".DynamicTaskScheduler 开始执行:"+task.getName());
            // 使用反射调用指定类的方法
            BaseSchedulerTask bean = SpringBeanUtil.getBean(task.getClassName());
            bean.setLogCapture(consoleLogCapture);
            bean.execute(logid,task.getParameters());
            consoleLogCapture.EndwriteToBuffer(logid,this.getClass().getPackage().getName() +".DynamicTaskScheduler 结束任务:"+task.getName());
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException("执行任务失败: " + task.getName(), e);
        }
    }
    /**
     * 立即执行一次任务（手动触发）
     */
    public boolean executeTaskNow(String taskId) {
        ScheduledTask task = scheduledTaskMapper.selectById(taskId);
        if (task != null) {
            try {
                // 创建单独的线程执行，避免阻塞调度线程
                new Thread(() -> {
                    ScheduledTaskLog log = new ScheduledTaskLog(task.getId(), task.getName());
                    String logId = taskLogService.addLog(log);
                    currentExecutions.put(task.getId(), logId);

                    try {
                        // 开始捕获控制台日志
                        consoleLogCapture.startCapture(logId);

                        executeTask(task,logId);

                        // 停止捕获并保存控制台日志
                        String consoleLog = consoleLogCapture.stopCapture(logId);
                        log.setConsoleLog(consoleLog);
                        log.markSuccess("手动执行成功");
                    } catch (Exception e) {
                        // 停止捕获并保存控制台日志
                        String consoleLog = consoleLogCapture.stopCapture(logId);
                        log.setConsoleLog(consoleLog);
                        log.markFailed(e.getMessage());
                    } finally {
                        taskLogService.updateById(log);
                        currentExecutions.remove(task.getId());
                    }
                },"定时任务-手动执行").start();
                return true;
            } catch (Exception e) {
                e.printStackTrace();
                return false;
            }
        }
        return false;
    }

    /**
     * 获取当前正在执行的任务日志
     */
    public String  getRealtimeConsoleLog(String taskId) {
        String logId = currentExecutions.get(taskId);
        if (logId != null) {
            return taskLogService.getRealtimeConsoleLog(logId);
        }
        return "";
    }

    /**
     * 停止当前正在执行的任务
     */
    public boolean stopCurrentExecution(String taskId) {
        // 注意：这里只能中断线程，对于不支持中断的操作可能无法立即停止
        ScheduledFuture<?> future = taskFutures.get(taskId);
        if (future != null && !future.isDone()) {
            return future.cancel(true);
        }
        return false;
    }
    public List<ScheduledTask> getAllTasks() {
        return scheduledTaskMapper.list();
    }

    public ScheduledTask getTask(String taskId) {
        return scheduledTaskMapper.selectById(taskId);
    }
}